﻿using System;
using System.Linq;
using System.Reflection;
using System.Text.Json.Serialization;
using Devonline.Core;

namespace Devonline.Http
{
    /// <summary>
    /// 查询过滤选项, 代表字段内的字段和值的关系
    /// 此对象只处理最终形态的简单表达式, 不处理嵌套的形式. 典型样式为: 
    /// Name eq '张三'
    /// Age gt 20
    /// Name co '张三'
    /// not support: not logic
    /// not support: contains(Name, '张三')
    /// not support: contains(tolower(Name), 'lucy')
    /// </summary>
    public class FilterOption
    {
        /// <summary>
        /// 当前简单模式的过滤表达式
        /// </summary>
        protected readonly string _filter;
        /// <summary>
        /// 当前表达式的类型主体
        /// </summary>
        protected readonly Type _type;

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public FilterOption()
        {
        }
        /// <summary>
        /// 接受字符串表达式 filter 参数的构造函数
        /// </summary>
        /// <param name="filter"></param>
        public FilterOption(Type type, string filter)
        {
            _type = type;
            _filter = filter;
            var values = _filter.Split(AppSettings.CHAR_SPACE, StringSplitOptions.RemoveEmptyEntries);
            if (values.Length != 3)
            {
                throw new ArgumentException($"filter {filter} expression error!");
            }

            Field = values[0];
            var member = _type.GetMember(Field, BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.GetField).FirstOrDefault();
            if (member == null || !(member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Field))
            {
                throw new ArgumentException($"the property or field {Field} of type {_type.Name} not exist!");
            }

            Operator = Enum.Parse<OperatorType>(values[1]);
            Value = values[2];
            if (member.ReflectedType == typeof(string) && Value.StartsWith(AppSettings.CHAR_QUOTE) && Value.EndsWith(AppSettings.CHAR_QUOTE))
            {
                Value = Value[1..^1];
            }
        }

        /// <summary>
        /// 字段名
        /// </summary>
        [JsonPropertyName("field")]
        public string Field { get; set; }
        /// <summary>
        /// 值
        /// </summary>
        [JsonPropertyName("value")]
        public string Value { get; set; }
        /// <summary>
        /// 字段和值的关系, eq, ne, gt, gte, lt, lte...
        /// </summary>
        [JsonPropertyName("operator")]
        public OperatorType? Operator { get; set; }

        /// <summary>
        /// 重写的 ToString 方法输出字符串形式的表达式
        /// </summary>
        /// <returns></returns>
        public override string ToString() => $"{Field} {Operator} {Value}";
    }


    /// <summary>
    /// 查询过滤选项, 代表字段内的字段和值的关系
    /// 此对象只处理最终形态的简单表达式, 不处理嵌套的形式. 典型样式为: 
    /// Name eq '张三'
    /// Age gt 20
    /// Name co '张三'
    /// not support: not logic
    /// not support: contains(Name, '张三')
    /// not support: contains(tolower(Name), 'lucy')
    /// </summary>
    public class FilterOption<T>
    {
        /// <summary>
        /// 当前简单模式的过滤表达式
        /// </summary>
        protected readonly string _filter;
        /// <summary>
        /// 当前表达式的类型主体
        /// </summary>
        protected readonly Type _type = typeof(T);

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public FilterOption()
        {
        }
        /// <summary>
        /// 接受字符串表达式 filter 参数的构造函数
        /// </summary>
        /// <param name="filter"></param>
        public FilterOption(string filter)
        {
            _filter = filter;
            var values = _filter.Split(AppSettings.CHAR_SPACE, StringSplitOptions.RemoveEmptyEntries);
            if (values.Length != 3)
            {
                throw new ArgumentException($"filter {filter} expression error!");
            }

            Field = values[0];
            var member = _type.GetMember(Field, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.GetProperty | BindingFlags.GetField).FirstOrDefault();
            if (member == null || !(member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Field))
            {
                throw new ArgumentException($"the property or field {Field} of type {_type.Name} not exist!");
            }

            Operator = values[1].GetEnumValueByJsonName<OperatorType>();
            Value = values[2];
            FieldType = member.GetMemberType();
            if (FieldType.IsValueType)
            {
                FieldValue = Convert.ChangeType(Value, FieldType);
            }
            else if (FieldType == typeof(string) && Value.StartsWith(AppSettings.CHAR_QUOTE) && Value.EndsWith(AppSettings.CHAR_QUOTE))
            {
                Value = Value[1..^1];
                FieldValue = Value;
            }
            else
            {
                FieldValue = Value;
            }
        }

        /// <summary>
        /// 字段名
        /// </summary>
        [JsonPropertyName("field")]
        public string Field { get; set; }
        /// <summary>
        /// 值
        /// </summary>
        [JsonPropertyName("value")]
        public string Value { get; set; }
        /// <summary>
        /// 字段和值的关系, eq, ne, gt, gte, lt, lte...
        /// </summary>
        [JsonPropertyName("operator")]
        public OperatorType? Operator { get; set; }
        /// <summary>
        /// field type
        /// </summary>
        public Type FieldType { get; private set; }
        /// <summary>
        /// value 对应的原始类型值
        /// </summary>
        public object FieldValue { get; private set; }

        /// <summary>
        /// 重写的 ToString 方法输出字符串形式的表达式
        /// </summary>
        /// <returns></returns>
        public override string ToString() => $"{Field} {Operator} {Value}";
    }
}
